/*	Copyright (c) 2010, 2011 MIEM (http://miem.edu.ru/)
 *
 *	Authors:
 *		* Andrey Shtykovskiy    ( ashty@itas.miem.edu.ru      )
 *		* Edward Klyshinsky     ( klyshinsky@itas.miem.edu.ru )
 *		* Sergey R. Tumkovsky   ( srt@itas.miem.edu.ru        )
 *
 *	This file is part of MOAN (morphology analysis) software.
 *
 *	MOAN is free software: you can redistribute it and/or modify it 
 *	under the terms of the GNU General Public License as published 
 *	by the Free Software Foundation, either version 3 of the License, 
 *	or (at your option) any later version.
 *
 *	This library is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *	Lesser General Public License for more details.
 *
 *	You should have received a copy of the GNU General Public License 
 *	along with MOAN. If not, see http://www.gnu.org/licenses/.
 */

#ifndef __SHELL_UNITTEST_HPP_GUARD__
#define __SHELL_UNITTEST_HPP_GUARD__

#include <stdint.h>

#include "gtest/gtest.h"

#include "moan/shell.hpp"


class shell_single_parameter : public ::testing::Test {

	struct parameter_struct {
		parameter_struct() : parameter(0) { }
		int parameter;
	};

	struct parameter_pod_struct {
		int parameter;
	};

	struct parameter_reference_struct {

		parameter_reference_struct() : parameter(NULL) { }
		~parameter_reference_struct() { delete parameter; }

		parameter_struct *parameter;
	};

	template<typename parameter_ty>
	class parameter_class {
	private:
		parameter_ty _parameter;
	public:
		typedef parameter_ty parameter_type;

		parameter_class() : _parameter(0) { }

		parameter_type get_parameter() const {
			return _parameter;
		}

		void set_parameter(parameter_type parameter) {
			_parameter = parameter;
		}
	};

protected:
	typedef parameter_struct parameter_struct_t;
	typedef moan::shell<parameter_struct> shell_struct_t;
	typedef moan::shell<parameter_pod_struct> shell_pod_struct_t;
	typedef moan::shell<parameter_reference_struct> shell_ref_struct_t;
	typedef moan::shell< parameter_class<int> > shell_parameter_class_int_t;

	virtual void SetUp() {
		shell_struct = new shell_struct_t();
		shell_pod_struct = new shell_pod_struct_t();
		shell_ref_struct = new shell_ref_struct_t();
		shell_class = new shell_parameter_class_int_t();
	}

	virtual void TearDown() {
		delete shell_struct;
		shell_struct = NULL;

		delete shell_pod_struct;
		shell_pod_struct = NULL;

		delete shell_ref_struct;
		shell_ref_struct = NULL;

		delete shell_class;
		shell_class = NULL;
	}

	shell_struct_t *shell_struct;
	shell_pod_struct_t *shell_pod_struct;
	shell_ref_struct_t *shell_ref_struct;
	shell_parameter_class_int_t *shell_class;
};

TEST_F(shell_single_parameter, struct_create) {

	ASSERT_EQ(0, shell_struct->parameter);
}

TEST_F(shell_single_parameter, struct_rw) {

	shell_struct->parameter = 10;

	ASSERT_EQ(10, shell_struct->parameter);
}

TEST_F(shell_single_parameter, struct_pod_rw) {

	shell_pod_struct->parameter = 100;

	ASSERT_EQ(100, shell_pod_struct->parameter);
}

TEST_F(shell_single_parameter, struct_ref_rw) {

	shell_ref_struct->parameter = new parameter_struct_t();
	shell_ref_struct->parameter->parameter = 100;

	ASSERT_EQ(100, shell_ref_struct->parameter->parameter);
}

TEST_F(shell_single_parameter, class_create) {

	ASSERT_EQ(0, shell_class->get_parameter());
}

TEST_F(shell_single_parameter, class_rw) {

	shell_class->set_parameter(100);

	ASSERT_EQ(100, shell_class->get_parameter());
}

class shell_multiple_parameter : public ::testing::Test {

	struct parameter_struct {
		int value;
	};

	class parameter_class_id {
	private:
		int _id;
	public:
		parameter_class_id() : _id(0) { }

		int get() const {
			return _id;
		}

		void set(int id) {
			_id = id;
		}
	};

protected:
	typedef moan::shell<parameter_class_id, parameter_struct> two_parameters_shell_t;

	virtual void SetUp() {
		two_parameters = new two_parameters_shell_t();
	}

	virtual void TearDown() {
		delete two_parameters;
		two_parameters = NULL;
	}

	two_parameters_shell_t *two_parameters;
};

TEST_F(shell_multiple_parameter, create) {

	two_parameters->value = 0;

	ASSERT_EQ(0, two_parameters->value);
	ASSERT_EQ(0, two_parameters->get());
}

#endif /* __SHELL_UNITTEST_HPP_GUARD__ */
